package core

import (
	"context"
	"gitee.com/igolang/imoney/internal/router"
	"gitee.com/igolang/pkg/boot"
	"gitee.com/igolang/pkg/xcfg"
	"gitee.com/igolang/pkg/xgin"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

type httpServerCfg struct {
	Addr           string
	ReadTimeout    int
	WriteTimeout   int
	MaxConcurrency int
	Debug          bool
	DebugPrefix    string
	Monitoring     bool
}

type httpApp struct {
	serv   *http.Server
	Config *httpServerCfg
}

func Http(addr string) *httpApp {
	var cfg httpServerCfg
	if err := xcfg.UnmarshalKey("server", &cfg); err != nil {
		log.Fatalln("core read http server config err:", err)
		return nil
	}
	if addr != "" {
		cfg.Addr = addr
	}

	return &httpApp{
		Config: &cfg,
	}
}

func (h *httpApp) Init() error {
	defer log.Printf("pid[%d]: http server started listening on [%s]\n", boot.Pid, h.Config.Addr)
	serv := &http.Server{
		Addr:         h.Config.Addr,
		Handler:      h.gin(),
		ReadTimeout:  time.Duration(h.Config.ReadTimeout) * time.Millisecond,
		WriteTimeout: time.Duration(h.Config.WriteTimeout) * time.Millisecond,
	}
	h.serv = serv
	go func() {
		if err := serv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("core.init http server err: %v\n", err)
		}
	}()

	return nil
}

func (h *httpApp) gin() *gin.Engine {
	gin.SetMode(gin.ReleaseMode)
	if h.Config.Debug {
		gin.SetMode(gin.DebugMode)
	}
	engine := gin.New()
	engine.MaxMultipartMemory = int64(xcfg.GetSizeInBytes("server.maxUploadSize"))
	router.Init(engine)
	xgin.SetEngine(engine)
	return engine
}

func (h *httpApp) Shutdown() error {
	defer log.Printf("pid[%d]: http server end listening on [%s]\n", boot.Pid, h.Config.Addr)
	timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	return h.serv.Shutdown(timeout)
}

func (h *httpApp) Name() string {
	return "http service"
}
